home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / program / freeli22.zip / FREELIB2.ASX < prev    next >
Text File  |  1996-09-01  |  73KB  |  2,710 lines

  1. ~~~C_STR1
  2. Ideal
  3.  
  4. Public      strlen,strcpy,strcat,strcmp
  5.  
  6. Model Tiny
  7. CodeSeg
  8. P186
  9.  
  10. ;****************** strlen() -- Get length of string
  11. ;int strlen(char *strp);
  12.  
  13. strp        equ bp+4
  14.  
  15. Proc        strlen
  16.  
  17.             push bp                 ;Set up stack frame
  18.             mov bp,sp
  19.             push si                 ;Save SI
  20.  
  21.             mov si,[strp]           ;SI = string pointer
  22.  
  23. p1_loop:    lodsb                   ;Load char
  24.             test al,al              ;Loop while not zero
  25.             jnz p1_loop
  26.  
  27.             sub si,[strp]           ;AX = length
  28.             dec si
  29.             xchg ax,si
  30.  
  31.             pop si                  ;Restore SI
  32.             pop bp                  ;Delete stack frame
  33.             ret 2                   ;Return
  34.  
  35. EndP        strlen
  36.  
  37. ;****************** strcpy() -- Copy a string
  38. ;void strcpy(char *str1, char *str2);
  39.  
  40. str1        equ bp+6
  41. str2        equ bp+4
  42.  
  43. Proc        strcpy
  44.  
  45.             push bp                 ;Set up stack frame
  46.             mov bp,sp
  47.             pusha                   ;Save all registers
  48.  
  49.             mov si,[str2]           ;SI = source
  50.             mov di,[str1]           ;DI = destination
  51.  
  52. p2_loop:    lodsb                   ;Load char
  53.             mov [di],al             ;Store char
  54.             inc di
  55.             test al,al              ;Loop while not zero
  56.             jnz p2_loop
  57.  
  58.             popa                    ;Restore registers
  59.             pop bp                  ;Delete stack frame
  60.             ret 4                   ;Return
  61.  
  62. EndP        strcpy
  63.  
  64. ;****************** strcat() -- Concatenate strings
  65. ;void strcat(char *str1, char *str2);
  66.  
  67. str1        equ bp+6
  68. str2        equ bp+4
  69.  
  70. Proc        strcat
  71.  
  72.             push bp                 ;Set up stack frame
  73.             mov bp,sp
  74.             pusha                   ;Save all registers
  75.  
  76.             mov si,[str1]           ;SI = destination
  77.  
  78. p3_cloop:   lodsb                   ;Load char
  79.             test al,al              ;Loop while not zero
  80.             jnz p3_cloop
  81.  
  82.             mov di,si               ;DI = destination
  83.             mov si,[str2]           ;SI = source
  84.             dec di
  85.  
  86. p3_loop:    lodsb                   ;Load char
  87.             mov [di],al             ;Store char
  88.             inc di
  89.             test al,al              ;Loop while not zero
  90.             jnz p3_loop
  91.  
  92.             popa                    ;Restore registers
  93.             pop bp                  ;Delete stack frame
  94.             ret 4                   ;Return
  95.  
  96. EndP        strcat
  97.  
  98. ;****************** strcmp() -- Compare strings
  99. ;void strcmp(char *str1, char *str2);
  100.  
  101. str1        equ bp+6
  102. str2        equ bp+4
  103.  
  104. Proc        strcmp
  105.  
  106.             push bp                 ;Set up stack frame
  107.             mov bp,sp
  108.             push si di              ;Save registers
  109.  
  110.             mov si,[str1]           ;SI = source
  111.             mov di,[str2]           ;DI = destination
  112.  
  113. p4_loop:    lodsb                   ;Load char 1
  114.             mov ah,[di]             ;Load char 2
  115.             inc di
  116.             cmp al,ah               ;Not equal?
  117.             jne p4_nope
  118.             test al,al              ;Loop while not zero
  119.             jnz p4_loop
  120.  
  121.             xor ax,ax               ;Equal, return 0
  122. p4_done:    pop di si               ;Restore registers
  123.             pop bp                  ;Delete stack frame
  124.             ret 4                   ;Return
  125.  
  126. p4_nope:    sub al,ah               ;Not equal, return difference
  127.             cbw                     ;in first unequal position
  128.             jmp p4_done
  129.  
  130. EndP        strcmp
  131.  
  132. End
  133.  
  134. ~~~C_STR2
  135. Ideal
  136.  
  137. Extrn       strlen:near
  138. Public      strchr,strstr
  139.  
  140. Model Tiny
  141. CodeSeg
  142. P186
  143.  
  144. ;****************** strchr() -- Search string for char
  145. ;int strchr(char *strp, int chr);
  146.  
  147. strp        equ bp+6
  148. chr         equ bp+4
  149.  
  150. Proc        strchr
  151.  
  152.             push bp                 ;Set up stack frame
  153.             mov bp,sp
  154.             push si                 ;Save SI
  155.  
  156.             mov si,[strp]           ;SI = string pointer
  157.             mov ah,[chr]            ;AH = char
  158.  
  159. p1_loop:    lodsb                   ;Load char
  160.             test al,al              ;Null, not found
  161.             jz p1_nope
  162.             cmp al,ah               ;Loop while not equal
  163.             jne p1_loop
  164.  
  165.             sub si,[strp]           ;AX = position of char
  166.             dec si
  167.             xchg ax,si
  168.  
  169. p1_done:    pop si                  ;Restore SI
  170.             pop bp                  ;Delete stack frame
  171.             ret 4                   ;Return
  172.  
  173. p1_nope:    mov ax,-1               ;Not found, return -1
  174.             jmp p1_done
  175.  
  176. EndP        strchr
  177.  
  178. ;****************** strstr() -- Search string for substring
  179. ;int strstr(char *strp, char *subp);
  180.  
  181. strp        equ bp+6
  182. subp        equ bp+4
  183.  
  184. Proc        strstr
  185.  
  186.             push bp                 ;Set up stack frame
  187.             mov bp,sp
  188.             pusha                   ;Save registers
  189.             push es
  190.  
  191.             push ds                 ;ES = DS
  192.             pop es
  193.  
  194.             mov si,[strp]           ;SI = string pointer
  195.             mov bx,[subp]           ;BX = substring pointer
  196.             push bx                 ;Get length of substring
  197.             call strlen             ;into DX
  198.             xchg dx,ax
  199.             mov ah,[bx]             ;AH = first char
  200.  
  201. p3_loop:    lodsb                   ;Load char
  202.             test al,al              ;Null, not found
  203.             jz p3_nope
  204.             cmp al,ah               ;Loop while not equal
  205.             jne p3_loop
  206.  
  207.             mov cx,dx               ;CX = length
  208.             mov di,bx               ;DI = substring
  209.             push si                 ;Save SI
  210.             dec si                  ;Push back char
  211.             repe cmpsb              ;Compare strings
  212.             pop si                  ;Restore SI
  213.             jne p3_loop             ;Loop if not equal
  214.  
  215.             sub si,[strp]           ;AX = position of char
  216.             dec si
  217.             
  218. p3_done:    mov [bp-2],si           ;Change pushed AX
  219.             pop es                  ;Restore registers
  220.             popa
  221.             pop bp                  ;Delete stack frame
  222.             ret 4                   ;Return
  223.  
  224. p3_nope:    mov si,-1               ;Not found, return -1
  225.             jmp p3_done
  226.  
  227. EndP        strstr
  228.  
  229. End
  230.  
  231. ~~~C_STR3
  232. Ideal
  233.  
  234. Public      stricmp,strlwr,strupr
  235.  
  236. Model Tiny
  237. CodeSeg
  238. P186
  239.  
  240. ;****************** stricmp() -- Compare strings, case insensitive
  241. ;void stricmp(char *str1, char *str2);
  242.  
  243. str1        equ bp+6
  244. str2        equ bp+4
  245.  
  246. Proc        stricmp
  247.  
  248.             push bp                 ;Set up stack frame
  249.             mov bp,sp
  250.             push si di              ;Save registers
  251.  
  252.             mov si,[str1]           ;SI = source
  253.             mov di,[str2]           ;DI = destination
  254.  
  255. p1_loop:    lodsb                   ;Load char 1
  256.             mov ah,[di]             ;Load char 2
  257.             inc di
  258.  
  259.             cmp al,'a'              ;Convert AL to uppercase
  260.             jb p1_setAH
  261.             cmp al,'z'
  262.             ja p1_setAH
  263.             sub al,20h
  264.  
  265. p1_setAH:   cmp ah,'a'              ;Convert AH to uppercase
  266.             jb p1_comp
  267.             cmp ah,'z'
  268.             ja p1_comp
  269.             sub ah,20h
  270.  
  271. p1_comp:    cmp al,ah               ;Equal?
  272.             jne p1_nope
  273.             test al,al              ;Loop while not zero
  274.             jnz p1_loop
  275.  
  276.             inc ax                  ;Equal, return 1
  277.  
  278. p1_done:    pop di si               ;Restore registers
  279.             pop bp                  ;Delete stack frame
  280.             ret 4                   ;Return
  281.  
  282. p1_nope:    xor ax,ax               ;Not equal, return 0
  283.             jmp p1_done
  284.  
  285. EndP        stricmp
  286.  
  287. ;****************** strlwr() -- Convert string to lowercase
  288. ;int strlwr(char *strp);
  289.  
  290. strp        equ bp+4
  291.  
  292. Proc        strlwr
  293.  
  294.             push bp                 ;Set up stack frame
  295.             mov bp,sp
  296.             pusha                   ;Save registers
  297.  
  298.             mov si,[strp]           ;SI = string pointer
  299.  
  300. p2_loop:    lodsb                   ;Load char
  301.             test al,al              ;Check for null
  302.             jz p2_done
  303.             cmp al,'A'              ;Check for uppercase
  304.             jb p2_loop
  305.             cmp al,'Z'
  306.             ja p2_loop
  307.             add al,20h              ;Convert to lowercase
  308.             mov [si-1],al           ;Store char
  309.             jmp p2_loop
  310.  
  311. p2_done:    popa                    ;Restore registers
  312.             pop bp                  ;Delete stack frame
  313.             ret 2                   ;Return
  314.  
  315. EndP        strlwr
  316.  
  317. ;****************** strupr() -- Convert string to uppercase
  318. ;int strupr(char *strp);
  319.  
  320. strp        equ bp+4
  321.  
  322. Proc        strupr
  323.  
  324.             push bp                 ;Set up stack frame
  325.             mov bp,sp
  326.             pusha                   ;Save registers
  327.  
  328.             mov si,[strp]           ;SI = string pointer
  329.  
  330. p3_loop:    lodsb                   ;Load char
  331.             test al,al              ;Check for null
  332.             jz p3_done
  333.             cmp al,'a'              ;Check for lowercase
  334.             jb p3_loop
  335.             cmp al,'z'
  336.             ja p3_loop
  337.             sub al,20h              ;Convert to uppercase
  338.             mov [si-1],al           ;Store char
  339.             jmp p3_loop
  340.  
  341. p3_done:    popa                    ;Restore registers
  342.             pop bp                  ;Delete stack frame
  343.             ret 2                   ;Return
  344.  
  345. EndP        strupr
  346.  
  347. End
  348.  
  349. ~~~C_STR4
  350. Ideal
  351.  
  352. Public      strrtrim,strltrim
  353.  
  354. Model Tiny
  355. CodeSeg
  356. P186
  357.  
  358. ;****************** strrtrim() -- Trim trailing spaces off a string
  359. ;int strrtrim(char *strp);
  360.  
  361. strp        equ bp+4
  362.  
  363. Proc        strrtrim
  364.  
  365.             push bp                 ;Set up stack frame
  366.             mov bp,sp
  367.             pusha                   ;Save registers
  368.  
  369.             mov si,[strp]           ;SI = string pointer
  370.             mov di,si               ;DI = SI
  371.  
  372. p1_loop:    lodsb                   ;Load char
  373.             test al,al              ;Check for null
  374.             jz p1_done
  375.             cmp al,' '              ;Check for space
  376.             je p1_loop
  377.             mov di,si               ;Set pointer
  378.             jmp p1_loop
  379.  
  380. p1_done:    mov [byte di+1],al      ;Terminate string
  381.             popa                    ;Restore registers
  382.             pop bp                  ;Delete stack frame
  383.             ret 2                   ;Return
  384.  
  385. EndP        strrtrim
  386.  
  387. ;****************** strltrim() -- Trim leading spaces off a string
  388. ;int strltrim(char *strp);
  389.  
  390. strp        equ bp+4
  391.  
  392. Proc        strltrim
  393.  
  394.             push bp                 ;Set up stack frame
  395.             mov bp,sp
  396.             pusha                   ;Save registers
  397.  
  398.             mov si,[strp]           ;SI, DI = string pointer
  399.             mov di,si
  400.  
  401. p2_loop:    lodsb                   ;Load char
  402.             test al,al              ;Check for null
  403.             jz p2_cont
  404.             cmp al,' '              ;Loop while space
  405.             je p2_loop
  406.  
  407. p2_cont:    dec si                  ;Move back one char
  408.             cmp si,di               ;No spaces, quit
  409.             je p2_done
  410.  
  411. p2_cloop:   lodsb                   ;Shift the string over
  412.             mov [di],al
  413.             inc di
  414.             test al,al
  415.             jnz p2_cloop
  416.  
  417. p2_done:    popa                    ;Restore registers
  418.             pop bp                  ;Delete stack frame
  419.             ret 2                   ;Return
  420.  
  421. EndP        strltrim
  422.  
  423. End
  424.  
  425. ~~~C_MEM1
  426. Ideal
  427.  
  428. Public      memcpy,memset
  429.  
  430. Model Tiny
  431. CodeSeg
  432. P186
  433.  
  434. ;****************** memcpy() -- Copy memory block
  435. ;void memcpy(void *p1, void *p2, int nbytes);
  436.  
  437. p1          equ bp+8
  438. p2          equ bp+6
  439. nbytes      equ bp+4
  440.  
  441. Proc        memcpy
  442.  
  443.             push bp                 ;Set up stack frame
  444.             mov bp,sp
  445.             push es                 ;Save registers
  446.             pusha
  447.  
  448.             push ds                 ;ES = DS
  449.             pop es
  450.  
  451.             mov si,[p2]             ;SI = source
  452.             mov di,[p1]             ;DI = destination
  453.             mov cx,[nbytes]         ;CX = count
  454.  
  455.             cmp di,si               ;Make forward moves
  456.             jb p1_go                ;in reverse
  457.             je p1_done
  458.  
  459.             std                     ;Set direction flag
  460.             add si,cx               ;Move offsets to end
  461.             add di,cx
  462.             dec si
  463.             dec di
  464.  
  465. p1_go:      rep movsb               ;Copy memory
  466.  
  467. p1_done:    cld                     ;Clear direction flag
  468.             popa                    ;Restore registers
  469.             pop es
  470.             pop bp                  ;Delete stack frame
  471.             ret 6                   ;Return
  472.  
  473. EndP        memcpy
  474.  
  475. ;****************** memset() -- Set memory block
  476. ;void memset(void *ptr, int nbytes, int chr);
  477.  
  478. ptr         equ bp+8
  479. nbytes      equ bp+6
  480. chr         equ bp+4
  481.  
  482. Proc        memset
  483.  
  484.             push bp                 ;Set up stack frame
  485.             mov bp,sp
  486.             push es                 ;Save registers
  487.             pusha
  488.  
  489.             push ds                 ;ES = DS
  490.             pop es
  491.  
  492.             mov di,[ptr]            ;DI = block
  493.             mov cx,[nbytes]         ;CX = count
  494.             mov al,[chr]            ;AL = char
  495.             rep stosb               ;Set memory
  496.  
  497.             popa                    ;Restore registers
  498.             pop es
  499.             pop bp                  ;Delete stack frame
  500.             ret 6                   ;Return
  501.  
  502. EndP        memset
  503.  
  504. End
  505.  
  506. ~~~C_MEM2
  507. Ideal
  508.  
  509. Public      memcmp,memchr
  510.  
  511. Model Tiny
  512. CodeSeg
  513. P186
  514.  
  515. ;****************** memcmp() -- Compare memory blocks
  516. ;void memcmp(void *p1, void *p2, int nbytes);
  517.  
  518. p1          equ bp+8
  519. p2          equ bp+6
  520. nbytes      equ bp+4
  521.  
  522. Proc        memcmp
  523.  
  524.             push bp                 ;Set up stack frame
  525.             mov bp,sp
  526.             push es                 ;Save registers
  527.             push cx si di
  528.  
  529.             push ds                 ;ES = DS
  530.             pop es
  531.  
  532.             mov si,[p2]             ;SI = source
  533.             mov di,[p1]             ;DI = destination
  534.             mov cx,[nbytes]         ;CX = count
  535.             repe cmpsb              ;Compare memory
  536.  
  537.             mov ax,1                ;Assume equal
  538.             je p1_done              ;Jump if equal
  539.  
  540.             xor ax,ax               ;Not equal, return 0
  541.  
  542. p1_done:    pop di si cx            ;Restore registers
  543.             pop es
  544.             pop bp                  ;Delete stack frame
  545.             ret 6                   ;Return
  546.  
  547. EndP        memcmp
  548.  
  549. ;****************** memchr() -- Scan memory for char
  550. ;void memchr(void *ptr, int nbytes, int chr);
  551.  
  552. ptr         equ bp+8
  553. nbytes      equ bp+6
  554. chr         equ bp+4
  555.  
  556. Proc        memchr
  557.  
  558.             push bp                 ;Set up stack frame
  559.             mov bp,sp
  560.             push es                 ;Save registers
  561.             push cx si di
  562.  
  563.             push ds                 ;ES = DS
  564.             pop es
  565.  
  566.             mov di,[ptr]            ;DI = block
  567.             mov cx,[nbytes]         ;CX = count
  568.             mov al,[chr]            ;AL = char
  569.             repne scasb             ;Scan memory
  570.             jne p2_nope             ;Jump if not found
  571.  
  572.             sub di,[ptr]            ;AX = position of char
  573.             dec di
  574.             xchg ax,di
  575.  
  576. p2_done:    pop di si cx            ;Restore registers
  577.             pop es
  578.             pop bp                  ;Delete stack frame
  579.             ret 6                   ;Return
  580.  
  581. p2_nope:    mov ax,-1               ;Not found, return -1
  582.             jmp p2_done
  583.  
  584. EndP        memchr
  585.  
  586. End
  587.  
  588. ~~~C_ISRCH
  589. Ideal
  590.  
  591. Public      isearch
  592.  
  593. Model Tiny
  594. P186
  595. CodeSeg
  596.  
  597. ;****************** isearch() -- Search a sorted array of integers
  598. ;int isearch(int *ary, int size, int elem);
  599.  
  600. ary         equ bp+8
  601. size        equ bp+6
  602. elem        equ bp+4
  603.  
  604. Proc        isearch
  605.  
  606.             push bp                 ;Set up stack frame
  607.             mov bp,sp
  608.             push bx cx dx si di     ;Save registers
  609.  
  610.             mov bx,[ary]            ;BX = array
  611.             xor cx,cx               ;CX = lower limit
  612.             mov dx,[size]           ;DX = upper limit
  613.             dec dx
  614.  
  615. p1_loop:    mov si,cx               ;SI = middle element
  616.             add si,dx
  617.             shr si,1
  618.             add si,si
  619.             mov ax,[bx+si]          ;Get element
  620.             shr si,1                ;Fix SI
  621.             cmp ax,[elem]           ;Check element
  622.             je p1_found             ;Equal?
  623.             jl p1_less              ;Too low?
  624.  
  625. p1_greater: mov di,si               ;Set first half
  626.             mov si,cx
  627.             jmp p1_cont
  628.  
  629. p1_less:    mov di,dx               ;Set second half
  630.             inc si
  631.  
  632. p1_cont:    cmp cx,dx               ;Min = Max, done
  633.             je p1_nope
  634.             mov cx,si               ;Set limits
  635.             mov dx,di
  636.             jmp p1_loop             ;Loop back
  637.  
  638. p1_found:   xchg ax,si              ;AX = result
  639.  
  640. p1_done:    pop di si dx cx bx      ;Restore registers
  641.             pop bp                  ;Delete stack frame
  642.             ret 6                   ;Return
  643.  
  644. p1_nope:    mov ax,-1               ;Not found, return -1
  645.             jmp p1_done
  646.  
  647. EndP        isearch
  648.  
  649. End
  650.  
  651. ~~~C_LSRCH
  652. Ideal
  653.  
  654. Public      lsearch
  655.  
  656. Model Tiny
  657. P186
  658. CodeSeg
  659.  
  660. ;****************** lsearch() -- Search a sorted array of longs
  661. ;int lsearch(long *ary, int size, long elem);
  662.  
  663. ary         equ bp+10
  664. size        equ bp+8
  665. elem        equ bp+4
  666.  
  667. Proc        lsearch
  668.  
  669.             push bp                 ;Set up stack frame
  670.             mov bp,sp
  671.             push bx cx dx si di     ;Save registers
  672.  
  673.             mov bx,[ary]            ;BX = array
  674.             xor cx,cx               ;CX = lower limit
  675.             mov dx,[size]           ;DX = upper limit
  676.             dec dx
  677.  
  678. p1_loop:    mov si,cx               ;SI = middle element
  679.             add si,dx
  680.             shr si,1
  681.             shl si,2
  682.             mov ax,[bx+si]          ;Get element
  683.             mov di,[bx+si+2]
  684.             shr si,2                ;Fix SI
  685.  
  686.             cmp di,[elem+2]         ;Check high word
  687.             jl p1_less              ;Too low?
  688.             jg p1_greater           ;Too high?
  689.             cmp ax,[elem]           ;Check low word
  690.             je p1_found             ;Equal?
  691.             jl p1_less              ;Too low?
  692.  
  693. p1_greater: mov di,si               ;Set first half
  694.             mov si,cx
  695.             dec di
  696.             jmp p1_cont
  697.  
  698. p1_less:    mov di,dx               ;Set second half
  699.             inc si
  700.  
  701. p1_cont:    cmp cx,dx               ;Min = Max, done
  702.             je p1_nope
  703.             mov cx,si               ;Set limits
  704.             mov dx,di
  705.             jmp p1_loop             ;Loop back
  706.  
  707. p1_found:   xchg ax,si              ;AX = result
  708.  
  709. p1_done:    pop di si dx cx bx      ;Restore registers
  710.             pop bp                  ;Delete stack frame
  711.             ret 8                   ;Return
  712.  
  713. p1_nope:    mov ax,-1               ;Not found, return -1
  714.             jmp p1_done
  715.  
  716. EndP        lsearch
  717.  
  718. End
  719.  
  720. ~~~C_XSRCH
  721. Ideal
  722.  
  723. Public      xsearch
  724.  
  725. Model Tiny
  726. P186
  727. CodeSeg
  728.  
  729. ;****************** xsearch() -- Search sorted array, generalized
  730. ;int xsearch(void **ary, int size, void *elem, void *func);
  731.  
  732. ary         equ bp+10
  733. size        equ bp+8
  734. elem        equ bp+6
  735. func        equ bp+4
  736.  
  737. Proc        xsearch
  738.  
  739.             push bp                 ;Set up stack frame
  740.             mov bp,sp
  741.             push bx cx dx si di     ;Save registers
  742.  
  743.             mov bx,[ary]            ;BX = array
  744.             xor cx,cx               ;CX = lower limit
  745.             mov dx,[size]           ;DX = upper limit
  746.             dec dx
  747.  
  748. p3_loop:    mov si,cx               ;SI = middle element
  749.             add si,dx
  750.             shr si,1
  751.             add si,si
  752.             mov ax,[bx+si]          ;Get element
  753.             shr si,1                ;Fix SI
  754.             push ax [elem]          ;Check element
  755.             call [word func]
  756.             test ax,ax
  757.             je p3_found             ;Equal?
  758.             jl p3_less              ;Too low?
  759.  
  760. p3_greater: mov di,si               ;Set first half
  761.             mov si,cx
  762.             jmp p3_cont
  763.  
  764. p3_less:    mov di,dx               ;Set second half
  765.             inc si
  766.  
  767. p3_cont:    cmp cx,dx               ;Min = Max, done
  768.             je p3_nope
  769.             mov cx,si               ;Set limits
  770.             mov dx,di
  771.             jmp p3_loop             ;Loop back
  772.  
  773. p3_found:   xchg ax,si              ;AX = result
  774.  
  775. p3_done:    pop di si dx cx bx      ;Restore registers
  776.             pop bp                  ;Delete stack frame
  777.             ret 8                   ;Return
  778.  
  779. p3_nope:    mov ax,-1               ;Not found, return -1
  780.             jmp p3_done
  781.  
  782. EndP        xsearch
  783.  
  784. End
  785.  
  786. ~~~C_SSRCH
  787. Ideal
  788.  
  789. Extrn       strcmp:near
  790. Public      ssearch
  791.  
  792. Model Tiny
  793. P186
  794. CodeSeg
  795.  
  796. ;****************** ssearch() -- Search a sorted array of strings
  797. ;int ssearch(char **ary, int size, char *elem);
  798.  
  799. ary         equ bp+8
  800. size        equ bp+6
  801. elem        equ bp+4
  802.  
  803. Proc        ssearch
  804.  
  805.             push bp                 ;Set up stack frame
  806.             mov bp,sp
  807.             push bx cx dx si di     ;Save registers
  808.  
  809.             mov bx,[ary]            ;BX = array
  810.             xor cx,cx               ;CX = lower limit
  811.             mov dx,[size]           ;DX = upper limit
  812.             dec dx
  813.  
  814. p1_loop:    mov si,cx               ;SI = middle element
  815.             add si,dx
  816.             shr si,1
  817.             add si,si
  818.             mov ax,[bx+si]          ;Get element
  819.             shr si,1                ;Fix SI
  820.             push ax [elem]          ;Check element
  821.             call strcmp
  822.             test ax,ax
  823.             je p1_found             ;Equal?
  824.             jl p1_less              ;Too low?
  825.  
  826. p1_greater: mov di,si               ;Set first half
  827.             mov si,cx
  828.             jmp p1_cont
  829.  
  830. p1_less:    mov di,dx               ;Set second half
  831.             inc si
  832.  
  833. p1_cont:    cmp cx,dx               ;Min = Max, done
  834.             je p1_nope
  835.             mov cx,si               ;Set limits
  836.             mov dx,di
  837.             dec di
  838.             jmp p1_loop             ;Loop back
  839.  
  840. p1_found:   xchg ax,si              ;AX = result
  841.  
  842. p1_done:    pop di si dx cx bx      ;Restore registers
  843.             pop bp                  ;Delete stack frame
  844.             ret 6                   ;Return
  845.  
  846. p1_nope:    mov ax,-1               ;Not found, return -1
  847.             jmp p1_done
  848.  
  849. EndP        ssearch
  850.  
  851. End
  852.  
  853. ~~~C_ISORT
  854. Ideal
  855.  
  856. Public      isort
  857.  
  858. Model Tiny
  859. P186
  860. CodeSeg
  861.  
  862. ;****************** isort() -- Sort an array of integers
  863. ;void isort(int *ary, int size);
  864.  
  865. ary         equ bp+6
  866. max         equ bp+4
  867.  
  868. Proc        isort
  869.  
  870.             push bp                 ;Set up stack frame
  871.             mov bp,sp
  872.             pusha                   ;Save all registers
  873.  
  874.             mov bx,[ary]            ;Call recursive routine
  875.             xor cx,cx
  876.             mov dx,[max]
  877.             dec dx
  878.             add dx,dx
  879.             call p1_qsort
  880.  
  881.             popa                    ;Restore registers
  882.             pop bp                  ;Delete stack frame
  883.             ret 4                   ;Return
  884.  
  885. p1_qsort:   cmp cx,dx               ;One element, return
  886.             je p1_ret
  887.             pusha
  888.  
  889.             mov ax,dx               ;Two elements, sort them
  890.             sub ax,cx
  891.             cmp ax,2
  892.             jne p1_cont
  893.  
  894.             mov si,cx               ;SI, DI = low, high
  895.             mov di,dx
  896.  
  897.             mov ax,[bx+si]          ;Check them
  898.             cmp ax,[bx+di]
  899.             jle p1_done
  900.  
  901.             xchg ax,[bx+di]         ;Switch them
  902.             mov [bx+si],ax
  903.             jmp p1_done
  904.  
  905. p1_cont:    mov si,cx               ;AX = middle element
  906.             add si,dx
  907.             shr si,2
  908.             add si,si
  909.             mov ax,[bx+si]
  910.  
  911.             mov si,cx               ;SI = low, DI = high
  912.             mov di,dx
  913.  
  914. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  915.             jge p1_loop2            ; SI < DX, advance SI
  916.             cmp ax,[bx+si]
  917.             jle p1_loop2
  918.             inc si
  919.             inc si
  920.             jmp p1_loop
  921.  
  922. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  923.             jle p1_cont2            ; DI > CX, advance DI
  924.             cmp ax,[bx+di]
  925.             jge p1_cont2
  926.             dec di
  927.             dec di
  928.             jmp p1_loop2
  929.  
  930. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  931.             jge p1_rec
  932.  
  933.             push [bx+si]            ;Swap elements
  934.             push [bx+di]
  935.             pop [bx+si]
  936.             pop [bx+di]
  937.             inc si                  ;Advance SI, DI
  938.             inc si
  939.             dec di
  940.             dec di
  941.  
  942.             jmp p1_loop             ;Loop back
  943.  
  944. p1_rec:     cmp cx,si               ;If first half isn't empty,
  945.             je p1_skip1             ;recurse to sort it
  946.             xchg dx,di
  947.             call p1_qsort
  948.             xchg dx,di
  949.  
  950. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  951.             je p1_done              ;recurse to sort it
  952.             xchg cx,si
  953.             call p1_qsort
  954.             xchg cx,si
  955.  
  956. p1_done:    popa                    ;Restore registers
  957. p1_ret:     ret                     ;Return
  958.  
  959. EndP        isort
  960.  
  961. End
  962.  
  963. ~~~C_LSORT
  964. Ideal
  965.  
  966. Public      lsort
  967.  
  968. Model Tiny
  969. P186
  970. CodeSeg
  971.  
  972. ;****************** lsort() -- Sort an array of longs
  973. ;void lsort(long *ary, int size);
  974.  
  975. ary         equ bp+6
  976. max         equ bp+4
  977. num         equ bp-4
  978.  
  979. Proc        lsort
  980.  
  981.             enter 4,0               ;Set up stack frame
  982.             pusha                   ;Save all registers
  983.  
  984.             mov bx,[ary]            ;Call recursive routine
  985.             xor cx,cx
  986.             mov dx,[max]
  987.             dec dx
  988.             shl dx,2
  989.             call p1_qsort
  990.  
  991.             popa                    ;Restore registers
  992.             leave                   ;Delete stack frame
  993.             ret 4                   ;Return
  994.  
  995. p1_done:    popa                    ;Restore registers
  996. p1_ret:     ret                     ;Return
  997.  
  998. p1_qsort:   cmp cx,dx               ;One element, return
  999.             je p1_ret
  1000.             pusha
  1001.  
  1002.             mov ax,dx               ;Two elements, sort them
  1003.             sub ax,cx
  1004.             cmp ax,4
  1005.             jne p1_cont
  1006.  
  1007.             mov si,cx               ;SI, DI = low, high
  1008.             mov di,dx
  1009.  
  1010.             mov dx,[bx+si+2]        ;Check them
  1011.             mov ax,[bx+si]
  1012.             cmp dx,[bx+di+2]
  1013.             jl p1_done
  1014.             jg p1_swap2
  1015.             cmp ax,[bx+di]
  1016.             jle p1_done
  1017.  
  1018. p1_swap2:   xchg ax,[bx+di]         ;Switch them
  1019.             mov [bx+si],ax
  1020.             xchg dx,[bx+di+2]
  1021.             mov [bx+si+2],dx
  1022.             jmp p1_done
  1023.  
  1024. p1_cont:    mov si,cx               ;NUM = middle element
  1025.             add si,dx
  1026.             shr si,3
  1027.             shl si,2
  1028.             mov ax,[bx+si]
  1029.             mov [num],ax
  1030.             mov ax,[bx+si+2]
  1031.             mov [num+2],ax
  1032.  
  1033.             mov si,cx               ;SI = low, DI = high
  1034.             mov di,dx
  1035.  
  1036. p1_loop:    cmp si,dx               ;While [BX+SI] < NUM and
  1037.             jge p1_loop2            ; SI < DX, advance SI
  1038.             mov ax,[num+2]
  1039.             cmp ax,[bx+si+2]
  1040.             jl p1_loop2
  1041.             jg p1_go1
  1042.             mov ax,[num]
  1043.             cmp ax,[bx+si]
  1044.             jle p1_loop2
  1045. p1_go1:     add si,4
  1046.             jmp p1_loop
  1047.  
  1048. p1_loop2:   cmp di,cx               ;While [BX+DI] > NUM and
  1049.             jle p1_cont2            ; DI > CX, advance DI
  1050.             mov ax,[num+2]
  1051.             cmp ax,[bx+di+2]
  1052.             jg p1_cont2
  1053.             jl p1_go2
  1054.             mov ax,[num]
  1055.             cmp ax,[bx+di]
  1056.             jge p1_cont2
  1057. p1_go2:     sub di,4
  1058.             jmp p1_loop2
  1059.  
  1060. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1061.             jge p1_rec
  1062.  
  1063.             push [bx+si]            ;Swap elements
  1064.             push [bx+di]
  1065.             pop [bx+si]
  1066.             pop [bx+di]
  1067.             push [bx+si+2]
  1068.             push [bx+di+2]
  1069.             pop [bx+si+2]
  1070.             pop [bx+di+2]
  1071.             add si,4                ;Advance SI, DI
  1072.             sub di,4
  1073.  
  1074.             jmp p1_loop             ;Loop back
  1075.  
  1076. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1077.             je p1_skip1             ;recurse to sort it
  1078.             xchg dx,di
  1079.             call p1_qsort
  1080.             xchg dx,di
  1081.  
  1082. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1083.             je p1_done2             ;recurse to sort it
  1084.             xchg cx,si
  1085.             call p1_qsort
  1086.             xchg cx,si
  1087.  
  1088. p1_done2:   jmp p1_done             ;Return
  1089.  
  1090. EndP        lsort
  1091.  
  1092. End
  1093.  
  1094. ~~~C_SSORT
  1095. Ideal
  1096.  
  1097. Extrn       strcmp:near
  1098. Public      ssort
  1099.  
  1100. Model Tiny
  1101. P186
  1102. CodeSeg
  1103.  
  1104. ;****************** ssort() -- Sort an array of strings
  1105. ;void ssort(char **ary, int size);
  1106.  
  1107. ary         equ bp+6
  1108. max         equ bp+4
  1109.  
  1110. Proc        ssort
  1111.  
  1112.             push bp                 ;Set up stack frame
  1113.             mov bp,sp
  1114.             pusha                   ;Save all registers
  1115.  
  1116.             mov bx,[ary]            ;Call recursive routine
  1117.             xor cx,cx
  1118.             mov dx,[max]
  1119.             dec dx
  1120.             add dx,dx
  1121.             call p1_qsort
  1122.  
  1123.             popa                    ;Restore registers
  1124.             pop bp                  ;Delete stack frame
  1125.             ret 4                   ;Return
  1126.  
  1127. p1_qsort:   cmp cx,dx               ;One element, return
  1128.             jne $+3
  1129.             ret
  1130.             pusha
  1131.  
  1132.             mov ax,dx               ;Two elements, sort them
  1133.             sub ax,cx
  1134.             cmp ax,2
  1135.             jne p1_cont
  1136.  
  1137.             mov si,cx               ;SI, DI = low, high
  1138.             mov di,dx
  1139.  
  1140.             mov ax,[bx+si]          ;Check them
  1141.             push ax [bx+di]
  1142.             call strcmp
  1143.             test ax,ax
  1144.             jle p1_done
  1145.  
  1146.             push [bx+si]            ;Switch them
  1147.             push [bx+di]
  1148.             pop [bx+si]
  1149.             pop [bx+di]
  1150.             jmp p1_done
  1151.  
  1152. p1_cont:    mov si,cx               ;AX = middle element
  1153.             add si,dx
  1154.             shr si,2
  1155.             add si,si
  1156.             mov ax,[bx+si]
  1157.  
  1158.             mov si,cx               ;SI = low, DI = high
  1159.             mov di,dx
  1160.  
  1161. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  1162.             jge p1_loop2            ; SI < DX, advance SI
  1163.             push ax ax [bx+si]
  1164.             call strcmp
  1165.             pop ax
  1166.             jle p1_loop2
  1167.             inc si
  1168.             inc si
  1169.             jmp p1_loop
  1170.  
  1171. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  1172.             jle p1_cont2            ; DI > CX, advance DI
  1173.             push ax ax [bx+di]
  1174.             call strcmp
  1175.             pop ax
  1176.             jge p1_cont2
  1177.             dec di
  1178.             dec di
  1179.             jmp p1_loop2
  1180.  
  1181. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1182.             jge p1_rec
  1183.  
  1184.             push [bx+si]            ;Swap elements
  1185.             push [bx+di]
  1186.             pop [bx+si]
  1187.             pop [bx+di]
  1188.             inc si                  ;Advance SI, DI
  1189.             inc si
  1190.             dec di
  1191.             dec di
  1192.  
  1193.             jmp p1_loop             ;Loop back
  1194.  
  1195. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1196.             je p1_skip1             ;recurse to sort it
  1197.             xchg dx,di
  1198.             call p1_qsort
  1199.             xchg dx,di
  1200.  
  1201. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1202.             je p1_done              ;recurse to sort it
  1203.             xchg cx,si
  1204.             call p1_qsort
  1205.             xchg cx,si
  1206.  
  1207. p1_done:    popa                    ;Restore registers
  1208. p1_ret:     ret                     ;Return
  1209.  
  1210. EndP        ssort
  1211.  
  1212. End
  1213.  
  1214. ~~~C_XSORT
  1215. Ideal
  1216.  
  1217. Public      xsort
  1218.  
  1219. Model Tiny
  1220. P186
  1221. CodeSeg
  1222.  
  1223. ;****************** xsort() -- Sort array, generalized
  1224. ;void xsort(void **ary, int size, void *func);
  1225.  
  1226. ary         equ bp+8
  1227. max         equ bp+6
  1228. func        equ bp+4
  1229.  
  1230. Proc        xsort
  1231.  
  1232.             push bp                 ;Set up stack frame
  1233.             mov bp,sp
  1234.             pusha                   ;Save all registers
  1235.  
  1236.             mov bx,[ary]            ;Call recursive routine
  1237.             xor cx,cx
  1238.             mov dx,[max]
  1239.             dec dx
  1240.             add dx,dx
  1241.             call p1_qsort
  1242.  
  1243.             popa                    ;Restore registers
  1244.             pop bp                  ;Delete stack frame
  1245.             ret 4                   ;Return
  1246.  
  1247. p1_qsort:   cmp cx,dx               ;One element, return
  1248.             jne $+3
  1249.             ret
  1250.             pusha
  1251.  
  1252.             mov ax,dx               ;Two elements, sort them
  1253.             sub ax,cx
  1254.             cmp ax,2
  1255.             jne p1_cont
  1256.  
  1257.             mov si,cx               ;SI, DI = low, high
  1258.             mov di,dx
  1259.  
  1260.             mov ax,[bx+si]          ;Check them
  1261.             push ax [bx+di]
  1262.             call [word func]
  1263.             test ax,ax
  1264.             jle p1_done
  1265.  
  1266.             push [bx+si]            ;Switch them
  1267.             push [bx+di]
  1268.             pop [bx+si]
  1269.             pop [bx+di]
  1270.             jmp p1_done
  1271.  
  1272. p1_cont:    mov si,cx               ;AX = middle element
  1273.             add si,dx
  1274.             shr si,2
  1275.             add si,si
  1276.             mov ax,[bx+si]
  1277.  
  1278.             mov si,cx               ;SI = low, DI = high
  1279.             mov di,dx
  1280.  
  1281. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  1282.             jge p1_loop2            ; SI < DX, advance SI
  1283.             push ax ax [bx+si]
  1284.             call [word func]
  1285.             pop ax
  1286.             jle p1_loop2
  1287.             inc si
  1288.             inc si
  1289.             jmp p1_loop
  1290.  
  1291. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  1292.             jle p1_cont2            ; DI > CX, advance DI
  1293.             push ax ax [bx+di]
  1294.             call [word func]
  1295.             pop ax
  1296.             jge p1_cont2
  1297.             dec di
  1298.             dec di
  1299.             jmp p1_loop2
  1300.  
  1301. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1302.             jge p1_rec
  1303.  
  1304.             push [bx+si]            ;Swap elements
  1305.             push [bx+di]
  1306.             pop [bx+si]
  1307.             pop [bx+di]
  1308.             inc si                  ;Advance SI, DI
  1309.             inc si
  1310.             dec di
  1311.             dec di
  1312.  
  1313.             jmp p1_loop             ;Loop back
  1314.  
  1315. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1316.             je p1_skip1             ;recurse to sort it
  1317.             xchg dx,di
  1318.             call p1_qsort
  1319.             xchg dx,di
  1320.  
  1321. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1322.             je p1_done              ;recurse to sort it
  1323.             xchg cx,si
  1324.             call p1_qsort
  1325.             xchg cx,si
  1326.  
  1327. p1_done:    popa                    ;Restore registers
  1328. p1_ret:     ret                     ;Return
  1329.  
  1330. EndP        xsort
  1331.  
  1332. End
  1333.  
  1334. ~~~C_LSHL
  1335. Ideal
  1336.  
  1337. Public      lshl
  1338.  
  1339. Model Tiny
  1340. CodeSeg
  1341. P186
  1342.  
  1343. ;****************** lshl() -- Shift long integer to the left
  1344. ;long lshl(long x, int d);    37 clocks (486)
  1345.  
  1346. x           equ bp+6
  1347. d           equ bp+4
  1348.  
  1349. Proc        lshl
  1350.  
  1351.             push bp                 ;Set up stack frame
  1352.             mov bp,sp
  1353.             push cx                 ;Save CX
  1354.  
  1355.             mov ax,[x]              ;DX:AX = x
  1356.             mov dx,[x+2]
  1357.             mov cl,[d]              ;CL = distance
  1358.  
  1359.             cmp cl,16               ;Distance > 16?
  1360.             jb p1_cont              ;Jump if not
  1361.  
  1362.             mov dx,ax               ;Shift left 16
  1363.             xor ax,ax
  1364.  
  1365. p1_cont:    and cl,15               ;Mask off high part
  1366.             push ax cx              ;Save AX, CX
  1367.             shl dx,cl               ;DX = (DX shl CL) +
  1368.             xor cl,15               ;     (AX shr (16 - CL))
  1369.             inc cx
  1370.             shr ax,cl
  1371.             add dx,ax
  1372.             pop cx ax               ;Restore AX, CX
  1373.             shl ax,cl               ;AX = AX shl CL
  1374.  
  1375.             pop cx                  ;Restore CX
  1376.             pop bp                  ;Delete stack frame
  1377.             ret 6                   ;Return
  1378.  
  1379. EndP        lshl
  1380.  
  1381. End
  1382.  
  1383. ~~~C_LSHR
  1384. Ideal
  1385.  
  1386. Public      lshr
  1387.  
  1388. Model Tiny
  1389. CodeSeg
  1390. P186
  1391.  
  1392. ;****************** lshr() -- Shift long integer to the right
  1393. ;long lshr(long x, int d);    37 clocks (486)
  1394.  
  1395. x           equ bp+6
  1396. d           equ bp+4
  1397.  
  1398. Proc        lshr
  1399.  
  1400.             push bp                 ;Set up stack frame
  1401.             mov bp,sp
  1402.             push cx                 ;Save CX
  1403.  
  1404.             mov ax,[x]              ;DX:AX = x
  1405.             mov dx,[x+2]
  1406.             mov cl,[d]              ;CL = distance
  1407.  
  1408.             cmp cl,16               ;Distance > 16?
  1409.             jb p1_cont              ;Jump if not
  1410.  
  1411.             mov ax,dx               ;Shift right 16
  1412.             xor dx,dx
  1413.  
  1414. p1_cont:    and cl,15               ;Mask off high part
  1415.             push dx cx              ;Save DX, CX
  1416.             shr ax,cl               ;AX = (AX shr CL) +
  1417.             xor cl,15               ;     (DX shl (16 - CL))
  1418.             inc cx
  1419.             shl dx,cl
  1420.             add ax,dx
  1421.             pop cx dx               ;Restore DX, CX
  1422.             shr dx,cl               ;DX = DX shr CL
  1423.  
  1424.             pop cx                  ;Restore CX
  1425.             pop bp                  ;Delete stack frame
  1426.             ret 6                   ;Return
  1427.  
  1428. EndP        lshr
  1429.  
  1430. End
  1431.  
  1432. ~~~C_LSAR
  1433. Ideal
  1434.  
  1435. Public      lsar
  1436.  
  1437. Model Tiny
  1438. CodeSeg
  1439. P186
  1440.  
  1441. ;****************** lsar() -- Shift long integer to the right, signed
  1442. ;long lsar(long x, int d);    39 clocks (486)
  1443.  
  1444. x           equ bp+6
  1445. d           equ bp+4
  1446.  
  1447. Proc        lsar
  1448.  
  1449.             push bp                 ;Set up stack frame
  1450.             mov bp,sp
  1451.             push cx                 ;Save CX
  1452.  
  1453.             mov ax,[x]              ;DX:AX = x
  1454.             mov dx,[x+2]
  1455.             mov cl,[d]              ;CL = distance
  1456.  
  1457.             cmp cl,16               ;Distance > 16?
  1458.             jb p1_cont              ;Jump if not
  1459.  
  1460.             mov ax,dx               ;Shift right 16
  1461.             cbw
  1462.  
  1463. p1_cont:    and cl,15               ;Mask off high part
  1464.             push dx cx              ;Save DX, CX
  1465.             shr ax,cl               ;AX = (AX shr CL) +
  1466.             xor cl,15               ;     (DX shl (16 - CL))
  1467.             inc cx
  1468.             shl dx,cl
  1469.             add ax,dx
  1470.             pop cx dx               ;Restore DX, CX
  1471.             sar dx,cl               ;DX = DX sar CL
  1472.  
  1473.             pop cx                  ;Restore CX
  1474.             pop bp                  ;Delete stack frame
  1475.             ret 6                   ;Return
  1476.  
  1477. EndP        lsar
  1478.  
  1479. End
  1480.  
  1481. ~~~C_LMUL
  1482. Ideal
  1483.  
  1484. Public      lmul
  1485.  
  1486. Model Tiny
  1487. CodeSeg
  1488. P186
  1489.  
  1490. ;****************** lmul() -- Multiply long integers
  1491. ;long lmul(long x, long y);   70 clocks (486)
  1492.  
  1493. x           equ bp+8
  1494. y           equ bp+4
  1495.  
  1496. Proc        lmul
  1497.  
  1498.             push bp                 ;Set up stack frame
  1499.             mov bp,sp
  1500.             push bx                 ;Save registers
  1501.  
  1502.             mov ax,[x]              ;Multiply low words
  1503.             mul [word y]
  1504.             mov bx,dx               ;BX = high word
  1505.             push ax                 ;Save low word
  1506.  
  1507.             mov ax,[x+2]            ;Multiply high by low Y
  1508.             mul [word y]
  1509.             add bx,ax               ;Add in result
  1510.  
  1511.             mov ax,[y+2]            ;Multiply high by low X
  1512.             mul [word x]
  1513.             add ax,bx               ;Add in result
  1514.  
  1515.             pop dx                  ;Restore low word
  1516.             xchg dx,ax              ;DX:AX = result
  1517.  
  1518.             pop bx                  ;Restore registers
  1519.             pop bp                  ;Delete stack frame
  1520.             ret 8                   ;Return
  1521.  
  1522. EndP        lmul
  1523.  
  1524. End
  1525.  
  1526. ~~~C_LIMUL
  1527. Ideal
  1528.  
  1529. Public      limul
  1530.  
  1531. Model Tiny
  1532. CodeSeg
  1533. P186
  1534.  
  1535. ;****************** limul() -- Multiply long integers, signed
  1536. ;long limul(long x, long y);   89-97 clocks (486)
  1537.  
  1538. x           equ bp+8
  1539. y           equ bp+4
  1540.  
  1541. Proc        limul
  1542.  
  1543.             push bp                 ;Set up stack frame
  1544.             mov bp,sp
  1545.             push bx cx              ;Save registers
  1546.  
  1547.             xor cx,cx               ;Clear neg flag
  1548.  
  1549.             mov ax,[x+2]            ;AX = x high word
  1550.             test ax,ax              ;Negative?
  1551.             jge p1_xok
  1552.             neg ax                  ;Negate X
  1553.             neg [word x]
  1554.             sbb ax,0
  1555.             not cx                  ;Set neg flag
  1556.  
  1557. p1_xok:     mov [x+2],ax            ;Save X
  1558.  
  1559.             mov ax,[y+2]            ;AX = y high word
  1560.             test ax,ax              ;Negative?
  1561.             jge p1_yok
  1562.             neg ax                  ;Negate Y
  1563.             neg [word y]
  1564.             sbb ax,0
  1565.             not cx                  ;Flip neg flag
  1566.  
  1567. p1_yok:     mov [y+2],ax            ;Save Y
  1568.  
  1569.             mov ax,[x]              ;Multiply low words
  1570.             mul [word y]
  1571.             mov bx,dx               ;BX = high word
  1572.             push ax                 ;Save low word
  1573.  
  1574.             mov ax,[x+2]            ;Multiply high by low Y
  1575.             mul [word y]
  1576.             add bx,ax               ;Add in result
  1577.  
  1578.             mov ax,[y+2]            ;Multiply high by low X
  1579.             mul [word x]
  1580.             add ax,bx               ;Add in result
  1581.  
  1582.             pop dx                  ;Restore low word
  1583.             xchg dx,ax              ;DX:AX = result
  1584.  
  1585.             test cx,cx              ;Check neg flag
  1586.             jz p1_done
  1587.  
  1588.             neg dx                  ;Negate result
  1589.             neg ax
  1590.             sbb dx,0
  1591.  
  1592. p1_done:    pop cx bx               ;Restore registers
  1593.             pop bp                  ;Delete stack frame
  1594.             ret 8                   ;Return
  1595.  
  1596. EndP        limul
  1597.  
  1598. End
  1599.  
  1600. ~~~C_LDIV
  1601. Ideal
  1602.  
  1603. Public      ldiv
  1604.  
  1605. Model Tiny
  1606. CodeSeg
  1607. P186
  1608.  
  1609. ;****************** ldiv() -- Divide long integers
  1610. ;long ldiv(long x, long y);   692-948 clocks (486)
  1611.  
  1612. x           equ bp+8
  1613. y           equ bp+4
  1614.  
  1615. Proc        ldiv
  1616.  
  1617.             push bp                 ;Set up stack frame
  1618.             mov bp,sp
  1619.             push bx cx si           ;Save registers
  1620.  
  1621.             xor ax,ax               ;Clear DX:AX, CX:BX
  1622.             xor bx,bx               ;DX:AX will contain
  1623.             xor cx,cx               ;the result, and
  1624.             xor dx,dx               ;CX:BX will be X.
  1625.             mov si,32               ;SI = count
  1626.  
  1627. p1_loop:    shl [word x],1          ;Shift in one bit of X
  1628.             rcl [word x+2],1
  1629.             adc bx,bx
  1630.             adc cx,cx
  1631.  
  1632.             add ax,ax               ;Shift result left by 1
  1633.             adc dx,dx
  1634.  
  1635.             cmp cx,[y+2]            ;Compare the partial X
  1636.             jb p1_skip              ;to Y, if X is bigger
  1637.             ja p1_sub               ;then Y is subtracted
  1638.             cmp bx,[y]              ;from the partial X.
  1639.             jb p1_skip
  1640.  
  1641. p1_sub:     sub bx,[y]              ;Subtract Y from partial X
  1642.             sbb cx,[y+2]
  1643.             add ax,1                ;Add one bit to result
  1644.             adc dx,0
  1645.  
  1646. p1_skip:    dec si                  ;Loop back
  1647.             jnz p1_loop
  1648.  
  1649.             pop si cx bx            ;Restore registers
  1650.             pop bp                  ;Delete stack frame
  1651.             ret 8                   ;Return
  1652.  
  1653. EndP        ldiv
  1654.  
  1655. End
  1656.  
  1657. ~~~C_LIDIV
  1658. Ideal
  1659.  
  1660. Public      lidiv
  1661.  
  1662. Model Tiny
  1663. CodeSeg
  1664. P186
  1665.  
  1666. ;****************** lidiv() -- Divide long integers, signed
  1667. ;long lidiv(long x, long y);   711-975 clocks (486)
  1668.  
  1669. x           equ bp+8
  1670. y           equ bp+4
  1671.  
  1672. Proc        lidiv
  1673.  
  1674.             push bp                 ;Set up stack frame
  1675.             mov bp,sp
  1676.             push bx cx si           ;Save registers
  1677.  
  1678.             xor cx,cx               ;Clear neg flag
  1679.  
  1680.             mov ax,[x+2]            ;AX = x high word
  1681.             test ax,ax              ;Negative?
  1682.             jge p1_xok
  1683.             neg ax                  ;Negate X
  1684.             neg [word x]
  1685.             sbb ax,0
  1686.             not cx                  ;Set neg flag
  1687.  
  1688. p1_xok:     mov [x+2],ax            ;Save X
  1689.  
  1690.             mov ax,[y+2]            ;AX = y high word
  1691.             test ax,ax              ;Negative?
  1692.             jge p1_yok
  1693.             neg ax                  ;Negate Y
  1694.             neg [word y]
  1695.             sbb ax,0
  1696.             not cx                  ;Flip neg flag
  1697.  
  1698. p1_yok:     mov [y+2],ax            ;Save Y
  1699.             push cx                 ;Save neg flag
  1700.  
  1701.             xor ax,ax               ;Clear DX:AX, CX:BX
  1702.             xor bx,bx               ;DX:AX will contain
  1703.             xor cx,cx               ;the result, and
  1704.             xor dx,dx               ;CX:BX will be X.
  1705.             mov si,32               ;SI = count
  1706.  
  1707. p1_loop:    shl [word x],1          ;Shift in one bit of X
  1708.             rcl [word x+2],1
  1709.             adc bx,bx
  1710.             adc cx,cx
  1711.  
  1712.             add ax,ax               ;Shift result left by 1
  1713.             adc dx,dx
  1714.  
  1715.             cmp cx,[y+2]            ;Compare the partial X
  1716.             jb p1_skip              ;to Y, if X is bigger
  1717.             ja p1_sub               ;then Y is subtracted
  1718.             cmp bx,[y]              ;from the partial X.
  1719.             jb p1_skip
  1720.  
  1721. p1_sub:     sub bx,[y]              ;Subtract Y from partial X
  1722.             sbb cx,[y+2]
  1723.             add ax,1                ;Add one bit to result
  1724.             adc dx,0
  1725.  
  1726. p1_skip:    dec si                  ;Loop back
  1727.             jnz p1_loop
  1728.  
  1729.             pop cx                  ;Restore neg flag
  1730.             test cx,cx              ;Check neg flag
  1731.             jz p1_done
  1732.  
  1733.             neg dx                  ;Negate result
  1734.             neg ax
  1735.             sbb dx,0
  1736.  
  1737. p1_done:    pop si cx bx            ;Restore registers
  1738.             pop bp                  ;Delete stack frame
  1739.             ret 8                   ;Return
  1740.  
  1741. EndP        lidiv
  1742.  
  1743. End
  1744.  
  1745. ~~~C_LMOD
  1746. Ideal
  1747.  
  1748. Extrn       ldiv:near,lmul:near
  1749. Public      lmod
  1750.  
  1751. Model Tiny
  1752. CodeSeg
  1753. P186
  1754.  
  1755. ;****************** lmod() -- Modulo on long integers
  1756. ;long lmod(long x, long y);
  1757.  
  1758. x           equ bp+8
  1759. y           equ bp+4
  1760.  
  1761. Proc        lmod
  1762.  
  1763.             push bp                 ;Set up stack frame
  1764.             mov bp,sp
  1765.  
  1766.             push [x] [x+2]          ;x MOD y = x - (x / y) * y
  1767.             push [y] [y+2]
  1768.             call ldiv
  1769.             push [y] [y+2]
  1770.             push dx ax
  1771.             call lmul
  1772.  
  1773.             neg dx                  ;Negate, add in X
  1774.             neg ax
  1775.             sbb dx,0
  1776.             add ax,[x]
  1777.             adc dx,[x+2]
  1778.  
  1779.             pop bp                  ;Delete stack frame
  1780.             ret 8                   ;Return
  1781.  
  1782. EndP        lmod
  1783.  
  1784. End
  1785.  
  1786. ~~~C_LIMOD
  1787. Ideal
  1788.  
  1789. Extrn       lidiv:near,limul:near
  1790. Public      limod
  1791.  
  1792. Model Tiny
  1793. CodeSeg
  1794. P186
  1795.  
  1796. ;****************** limod() -- Modulo on long integers, signed
  1797. ;long limod(long x, long y);
  1798.  
  1799. x           equ bp+8
  1800. y           equ bp+4
  1801.  
  1802. Proc        limod
  1803.  
  1804.             push bp                 ;Set up stack frame
  1805.             mov bp,sp
  1806.  
  1807.             push [x] [x+2]          ;x MOD y = x - (x / y) * y
  1808.             push [y] [y+2]
  1809.             call lidiv
  1810.             push [y] [y+2]
  1811.             push dx ax
  1812.             call limul
  1813.  
  1814.             neg dx                  ;Negate, add in X
  1815.             neg ax
  1816.             sbb dx,0
  1817.             add ax,[x]
  1818.             adc dx,[x+2]
  1819.  
  1820.             pop bp                  ;Delete stack frame
  1821.             ret 8                   ;Return
  1822.  
  1823. EndP        limod
  1824.  
  1825. End
  1826.  
  1827. ~~~C_FIXMUL
  1828. Ideal
  1829.  
  1830. Public      fixmul
  1831.  
  1832. Model Tiny
  1833. CodeSeg
  1834. P186
  1835.  
  1836. ;****************** fixmul() -- Multiply fixed point numbers
  1837. ;long fixmul(long x, long y);   101-109 clocks (486)
  1838.  
  1839. x           equ bp+8
  1840. y           equ bp+4
  1841.  
  1842. Proc        fixmul
  1843.  
  1844.             push bp                 ;Set up stack frame
  1845.             mov bp,sp
  1846.             push bx cx si           ;Save registers
  1847.  
  1848.             xor si,si               ;Clear neg flag
  1849.  
  1850.             mov ax,[x+2]            ;AX = x high word
  1851.             test ax,ax              ;Negative?
  1852.             jge p1_xok
  1853.             neg ax                  ;Negate X
  1854.             neg [word x]
  1855.             sbb ax,0
  1856.             not si                  ;Set neg flag
  1857.  
  1858. p1_xok:     mov [x+2],ax            ;Save X
  1859.  
  1860.             mov ax,[y+2]            ;AX = y high word
  1861.             test ax,ax              ;Negative?
  1862.             jge p1_yok
  1863.             neg ax                  ;Negate Y
  1864.             neg [word y]
  1865.             sbb ax,0
  1866.             not si                  ;Flip neg flag
  1867.  
  1868. p1_yok:     mov [y+2],ax            ;Save Y
  1869.  
  1870.             mov ax,[x+2]            ;Multiply high by low Y
  1871.             mul [word y]
  1872.             mov cx,dx               ;Save in CX:BX
  1873.             xchg bx,ax
  1874.  
  1875.             mov ax,[y+2]            ;Multiply high by low X
  1876.             mul [word x]
  1877.             add bx,ax               ;Add in result
  1878.             adc cx,dx
  1879.  
  1880.             mov ax,[x]              ;Multiply low words
  1881.             mul [word y]
  1882.             add bx,dx               ;Add in result
  1883.             adc cx,0
  1884.  
  1885.             mov ax,[x+2]            ;Multiply high words
  1886.             mul [word y+2]
  1887.             add ax,cx               ;Add in result
  1888.             mov dx,bx               ;DX:AX = result
  1889.             xchg dx,ax
  1890.  
  1891.             test si,si              ;Check neg flag
  1892.             jz p1_done
  1893.  
  1894.             neg dx                  ;Negate result
  1895.             neg ax
  1896.             sbb dx,0
  1897.  
  1898. p1_done:    pop si cx bx            ;Restore registers
  1899.             pop bp                  ;Delete stack frame
  1900.             ret 8                   ;Return
  1901.  
  1902. EndP        fixmul
  1903.  
  1904. End
  1905.  
  1906. ~~~C_FIXDIV
  1907. Ideal
  1908.  
  1909. Public      fixdiv
  1910.  
  1911. Model Tiny
  1912. CodeSeg
  1913. P186
  1914.  
  1915. ;****************** fixdiv() -- Divide fixed point numbers
  1916. ;long fixdiv(long x, long y);   1028-1412 clocks (486)
  1917.  
  1918. x           equ bp+8
  1919. y           equ bp+4
  1920.  
  1921. Proc        fixdiv
  1922.  
  1923.             push bp                 ;Set up stack frame
  1924.             mov bp,sp
  1925.             push bx cx si           ;Save registers
  1926.  
  1927.             xor cx,cx               ;Clear neg flag
  1928.  
  1929.             mov ax,[x+2]            ;AX = x high word
  1930.             test ax,ax              ;Negative?
  1931.             jge p1_xok
  1932.             neg ax                  ;Negate X
  1933.             neg [word x]
  1934.             sbb ax,0
  1935.             not cx                  ;Set neg flag
  1936.  
  1937. p1_xok:     mov [x+2],ax            ;Save X
  1938.  
  1939.             mov ax,[y+2]            ;AX = y high word
  1940.             test ax,ax              ;Negative?
  1941.             jge p1_yok
  1942.             neg ax                  ;Negate Y
  1943.             neg [word y]
  1944.             sbb ax,0
  1945.             not cx                  ;Flip neg flag
  1946.  
  1947. p1_yok:     mov [y+2],ax            ;Save Y
  1948.             push cx                 ;Save neg flag
  1949.  
  1950.             xor ax,ax               ;Clear DX:AX, CX:BX
  1951.             xor bx,bx               ;DX:AX will contain
  1952.             xor cx,cx               ;the result, and
  1953.             xor dx,dx               ;CX:BX will be X.
  1954.             mov si,48               ;SI = count
  1955.  
  1956. p1_loop:    shl [word x],1          ;Shift in one bit of X
  1957.             rcl [word x+2],1
  1958.             adc bx,bx
  1959.             adc cx,cx
  1960.  
  1961.             add ax,ax               ;Shift result left by 1
  1962.             adc dx,dx
  1963.  
  1964.             cmp cx,[y+2]            ;Compare the partial X
  1965.             jb p1_skip              ;to Y, if X is bigger
  1966.             ja p1_sub               ;then Y is subtracted
  1967.             cmp bx,[y]              ;from the partial X.
  1968.             jb p1_skip
  1969.  
  1970. p1_sub:     sub bx,[y]              ;Subtract Y from partial X
  1971.             sbb cx,[y+2]
  1972.             add ax,1                ;Add one bit to result
  1973.             adc dx,0
  1974.  
  1975. p1_skip:    dec si                  ;Loop back
  1976.             jnz p1_loop
  1977.  
  1978.             pop cx                  ;Restore neg flag
  1979.             test cx,cx              ;Check neg flag
  1980.             jz p1_done
  1981.  
  1982.             neg dx                  ;Negate result
  1983.             neg ax
  1984.             sbb dx,0
  1985.  
  1986. p1_done:    pop si cx bx            ;Restore registers
  1987.             pop bp                  ;Delete stack frame
  1988.             ret 8                   ;Return
  1989.  
  1990. EndP        fixdiv
  1991.  
  1992. End
  1993.  
  1994. ~~~C_TRIG
  1995. Ideal
  1996.  
  1997. Extrn       fixmul:near, fixdiv:near
  1998. Public      sine, cosine, tangent, cotangent
  1999. Public      secant, cosecant
  2000.  
  2001. Model Tiny
  2002. CodeSeg
  2003. P186
  2004.  
  2005. ;****************** TaylorSine() -- Calculate sine by Taylor series
  2006. ;long TaylorSine(long x);
  2007.  
  2008. ; *──────────────────────────────────────────────────*
  2009. ; │               x^3     x^5     x^7     x^9        │
  2010. ; │ sin(x) = x - ───── + ───── - ───── + ───── - ... │
  2011. ; │               3 !     5 !     7 !     9 !        │
  2012. ; *──────────────────────────────────────────────────*
  2013.  
  2014. x           equ bp+4
  2015.  
  2016. Proc        TaylorSine
  2017.  
  2018.             enter 2,0               ;Set up stack frame
  2019.             push bx cx si di        ;Save registers
  2020.  
  2021.             mov dx,[x+2]            ;First term = x
  2022.             mov ax,[x]
  2023.             xor cx,cx               ;Result = 0
  2024.             xor bx,bx
  2025.             mov [word bp-2],1       ;Count = 1
  2026.  
  2027. TS_loop:    add bx,ax               ;Add in term
  2028.             adc cx,dx
  2029.  
  2030.             mov si,[x]              ;DI:SI = x
  2031.             mov di,[x+2]
  2032.             push dx ax di si        ;term = last-term * x
  2033.             call fixmul
  2034.             push dx ax di si        ;term = last-term * x^2
  2035.             call fixmul
  2036.  
  2037.             mov di,dx               ;DI:SI = term
  2038.             xchg si,ax
  2039.             add [word bp-2],2       ;n = n + 2
  2040.             mov ax,[bp-2]           ;AX = n
  2041.             mov dx,[bp-2]           ;DX = n - 1
  2042.             dec dx
  2043.             mul dx                  ;AX = n * (n - 1)
  2044.             push di si ax 0         ;term = last-term * x^2 / n(n-1)
  2045.             call fixdiv             ;the next term in the series
  2046.  
  2047.             neg dx                  ;Invert sign
  2048.             neg ax
  2049.             sbb dx,0
  2050.  
  2051.             test ax,ax              ;Loop while not zero
  2052.             jnz TS_loop
  2053.             test dx,dx
  2054.             jnz TS_loop
  2055.  
  2056.             xchg ax,bx              ;Result in DX:AX
  2057.             mov dx,cx
  2058.  
  2059.             pop di si cx bx         ;Restore registers
  2060.             leave                   ;Delete stack frame
  2061.             ret 4                   ;Return
  2062.  
  2063. EndP        TaylorSine
  2064.  
  2065. Pi          dd 0003243Fh            ;Pi   (3.243F6A88... hex)
  2066. TwoPi       dd 0006487Fh            ;Pi*2 (6.487ED511... hex)
  2067. HalfPi      dd 00019220h            ;Pi/2 (1.921FB544... hex)
  2068.  
  2069. ;****************** sine() -- Trigonometric sine function
  2070. ;long sine(long x);
  2071.  
  2072. x           equ bp+4
  2073.  
  2074. Proc        sine
  2075.  
  2076.             push bp                 ;Set up stack frame
  2077.             mov bp,sp
  2078.  
  2079.             mov dx,[x+2]            ;DX:AX = x
  2080.             mov ax,[x]
  2081.             add ax,[word Pi]        ; x + Pi
  2082.             adc dx,[word Pi+2]
  2083.             push dx ax              ;Divide by 2*Pi
  2084.             push [word TwoPi+2]
  2085.             push [word TwoPi]
  2086.             call fixdiv
  2087.  
  2088.             xor ax,ax               ;Convert to integer
  2089.             push dx ax              ;Multiply by 2*Pi
  2090.             push [word TwoPi+2]
  2091.             push [word TwoPi]
  2092.             call fixmul
  2093.  
  2094.             neg dx                  ;Negate...
  2095.             neg ax
  2096.             sbb dx,0
  2097.             add ax,[x]              ;Add in X
  2098.             adc dx,[x+2]
  2099.  
  2100.             push dx ax              ;Calculate sine
  2101.             call TaylorSine
  2102.  
  2103.             pop bp                  ;Delete stack frame
  2104.             ret 4                   ;Return
  2105.  
  2106. EndP        sine
  2107.  
  2108. ;****************** cosine() -- Trigonometric cosine function
  2109. ;long cosine(long x);
  2110.  
  2111. x           equ bp+4
  2112.  
  2113. Proc        cosine
  2114.  
  2115.             push bp                 ;Set up stack frame
  2116.             mov bp,sp
  2117.  
  2118.             mov dx,[x+2]            ;DX:AX = x
  2119.             mov ax,[x]
  2120.             add ax,[word HalfPi]    ; x + Pi+2
  2121.             adc dx,[word HalfPi+2]
  2122.             push dx ax              ;cos(x) = sin(x + Pi/4)
  2123.             call sine
  2124.  
  2125.             pop bp                  ;Delete stack frame
  2126.             ret 4                   ;Return
  2127.  
  2128. EndP        cosine
  2129.  
  2130. ;****************** tangent() -- Trigonometric tangent function
  2131. ;long tangent(long x);
  2132.  
  2133. x           equ bp+4
  2134.  
  2135. Proc        tangent
  2136.  
  2137.             push bp                 ;Set up stack frame
  2138.             mov bp,sp
  2139.             push bx cx              ;Save registers
  2140.  
  2141.             push [x+2] [x]          ;CX:BX = sin(x)
  2142.             call sine
  2143.             mov cx,dx
  2144.             xchg bx,ax
  2145.             push [x+2] [x]          ;DX:AX = cos(x)
  2146.             call cosine
  2147.             push cx bx dx ax        ;tan(x) = sin(x) / cos(x)
  2148.             call fixdiv
  2149.  
  2150.             pop cx bx               ;Restore registers
  2151.             pop bp                  ;Delete stack frame
  2152.             ret 4                   ;Return
  2153.  
  2154. EndP        tangent
  2155.  
  2156. ;****************** cotangent() -- Trigonometric cotangent function
  2157. ;long cotangent(long x);
  2158.  
  2159. x           equ bp+4
  2160.  
  2161. Proc        cotangent
  2162.  
  2163.             push bp                 ;Set up stack frame
  2164.             mov bp,sp
  2165.             push bx cx              ;Save registers
  2166.  
  2167.             push [x+2] [x]          ;CX:BX = sin(x)
  2168.             call sine
  2169.             mov cx,dx
  2170.             xchg bx,ax
  2171.             push [x+2] [x]          ;DX:AX = cos(x)
  2172.             call cosine
  2173.             push dx ax cx bx        ;cot(x) = cos(x) / sin(x)
  2174.             call fixdiv
  2175.  
  2176.             pop cx bx               ;Restore registers
  2177.             pop bp                  ;Delete stack frame
  2178.             ret 4                   ;Return
  2179.  
  2180. EndP        cotangent
  2181.  
  2182. ;****************** secant() -- Trigonometric secant function
  2183. ;long secant(long x);
  2184.  
  2185. x           equ bp+4
  2186.  
  2187. Proc        secant
  2188.  
  2189.             push bp                 ;Set up stack frame
  2190.             mov bp,sp
  2191.  
  2192.             push [x+2] [x]          ;DX:AX = cos(x)
  2193.             call cosine
  2194.             push 1 0 dx ax          ;sec(x) = 1 / cos(x)
  2195.             call fixdiv
  2196.  
  2197.             pop bp                  ;Delete stack frame
  2198.             ret 4                   ;Return
  2199.  
  2200. EndP        secant
  2201.  
  2202. ;****************** cosecant() -- Trigonometric cosecant function
  2203. ;long cosecant(long x);
  2204.  
  2205. x           equ bp+4
  2206.  
  2207. Proc        cosecant
  2208.  
  2209.             push bp                 ;Set up stack frame
  2210.             mov bp,sp
  2211.  
  2212.             push [x+2] [x]          ;DX:AX = cos(x)
  2213.             call sine
  2214.             push 1 0 dx ax          ;csc(x) = 1 / sin(x)
  2215.             call fixdiv
  2216.  
  2217.             pop bp                  ;Delete stack frame
  2218.             ret 4                   ;Return
  2219.  
  2220. EndP        cosecant
  2221.  
  2222. End
  2223.  
  2224. ~~~C_FIXTOA
  2225. Ideal
  2226.  
  2227. Public      fixtoa
  2228.  
  2229. Model Tiny
  2230. CodeSeg
  2231. P186
  2232.  
  2233. ;****************** fixtoa() -- Convert fixed point number to string
  2234. ;void fixtoa(int n, char *strp);
  2235.  
  2236. n           equ bp+6
  2237. strp        equ bp+4
  2238.  
  2239. Proc        fixtoa
  2240.  
  2241.             push bp                 ;Set up stack frame
  2242.             mov bp,sp
  2243.             pusha                   ;Save all registers
  2244.  
  2245.             mov di,[strp]           ;DI = string pointer
  2246.             mov dx,[n+2]            ;DX:AX = n
  2247.             mov ax,[n]
  2248.  
  2249.             test dx,dx              ;Negative?
  2250.             jge p1_noneg
  2251.             mov [byte di],'-'       ;Store minus sign
  2252.             inc di
  2253.             neg dx                  ;Make it positive
  2254.             neg ax
  2255.             sbb dx,0
  2256.  
  2257. p1_noneg:   push dx                 ;Save DX
  2258.             xor bx,bx               ;Zero rem flag
  2259.             add ax,ax               ;Shift out high bit
  2260.             adc bx,0                ;BX = rem flag
  2261.             shr ax,1                ;Restore AX
  2262.  
  2263.             mov cx,50000            ;AX = AX * 50000
  2264.             mul cx
  2265.             shr ax,15               ;AX = AX / 32768
  2266.             shl dx,1
  2267.             or ax,dx
  2268.             pop dx                  ;Restore DX
  2269.             push bx ax              ;Save BX, AX
  2270.  
  2271.             xchg dx,ax              ;Integer part in AX
  2272.  
  2273.             xor cx,cx               ;Zero CX
  2274.             mov si,10               ;SI = 10
  2275.  
  2276. p1_dloop:   xor dx,dx               ;Divide by 10
  2277.             div si
  2278.             mov bl,dl               ;Remainder in BL
  2279.             add bl,30h              ;Convert to digit
  2280.             push bx                 ;Push digit
  2281.             inc cx
  2282.             test ax,ax              ;Loop back
  2283.             jnz p1_dloop
  2284.  
  2285. p1_ploop:   pop ax                  ;Pop digit
  2286.             mov [di],al             ;Store digit
  2287.             inc di
  2288.             loop p1_ploop           ;Loop back
  2289.  
  2290.             mov [byte di],'.'       ;Store decimal point
  2291.             inc di
  2292.             pop ax bx               ;Restore low data
  2293.             xor dx,dx               ;Zero DX
  2294.             test bx,bx              ;Check for high part
  2295.             jz p1_nohigh
  2296.  
  2297.             add ax,50000            ;Add in 50000
  2298.             adc dx,0
  2299.  
  2300. p1_nohigh:  mov si,10               ;SI = 10
  2301.             mov cx,5                ;5 digits
  2302.             jmp p1_skip1
  2303.  
  2304. p1_dloopb:  xor dx,dx               ;Zero DX
  2305. p1_skip1:   div si                  ;Divide by 10
  2306.             mov bl,dl               ;Remainder in BL
  2307.             add bl,30h              ;Convert to digit
  2308.             push bx                 ;Push digit
  2309.             loop p1_dloopb          ;Loop back
  2310.  
  2311.             mov cx,5                ;5 digits
  2312.  
  2313. p1_ploopb:  pop ax                  ;Pop digit
  2314.             mov [di],al             ;Store digit
  2315.             inc di
  2316.             loop p1_ploopb          ;Loop back
  2317.  
  2318.             mov [byte di],0         ;Add the null byte
  2319.  
  2320. p1_done:    popa                    ;Restore registers
  2321.             pop bp                  ;Delete stack frame
  2322.             ret 6                   ;Return
  2323.  
  2324. EndP        fixtoa
  2325.  
  2326. End
  2327.  
  2328. ~~~C_ATOFIX
  2329. Ideal
  2330.  
  2331. Public      atofix
  2332.  
  2333. Model Tiny
  2334. CodeSeg
  2335. P186
  2336.  
  2337. ;****************** atofix() -- Convert string to fixed point number
  2338. ;long atofix(char *strp);
  2339.  
  2340. strp        equ bp+4
  2341.  
  2342. Proc        atofix
  2343.  
  2344.             push bp                 ;Set up stack frame
  2345.             mov bp,sp
  2346.             push bx cx si di bp     ;Save registers
  2347.  
  2348.             mov si,[strp]           ;SI = string
  2349.  
  2350.             xor ax,ax               ;AX = 0
  2351.             xor bh,bh               ;BH = 0
  2352.             mov cx,10               ;CX = 10
  2353.  
  2354. p1_ploop:   mov bl,[si]             ;Load char
  2355.             inc si
  2356.             cmp bl,' '              ;Loop while char is space
  2357.             je p1_ploop             ;(20h, or 09h thru 0Dh)
  2358.             cmp bl,9
  2359.             jna p1_go
  2360.             cmp bl,13
  2361.             jbe p1_ploop
  2362.  
  2363. p1_go:      xor bp,bp               ;BP = 0
  2364.             cmp bl,'+'              ;If char = '+', ignore
  2365.             je p1_loop
  2366.             cmp bl,'-'              ;If char <> '-', keep it
  2367.             jne p1_skip
  2368.             inc bp                  ;Set negative flag
  2369.  
  2370. p1_loop:    mov bl,[si]             ;Load char
  2371.             inc si
  2372.  
  2373. p1_skip:    xor dx,dx               ;Clear DX
  2374.             cmp bl,'.'              ;Decimal point, continue
  2375.             je p1_cont
  2376.             cmp bl,'9'              ;Not a digit, finish
  2377.             ja p1_finish
  2378.             sub bl,'0'
  2379.             jc p1_finish
  2380.  
  2381.             mul cx                  ;Multiply by 10
  2382.             add ax,bx               ;Add in digit...
  2383.             jmp p1_loop             ;Loop back
  2384.  
  2385. p1_cont:    push ax                 ;Save integer part
  2386.             xor ax,ax               ;Zero AX
  2387.             mov di,1                ;DI = 1
  2388.  
  2389. p1_floop:   mov bl,[si]             ;Load char
  2390.             inc si
  2391.  
  2392.             cmp bl,'9'              ;Not a digit, finish
  2393.             ja p1_ffinish
  2394.             sub bl,'0'
  2395.             jc p1_ffinish
  2396.  
  2397.             mul cx                  ;Multiply by 10
  2398.             add ax,bx               ;Add in digit...
  2399.             adc dx,0
  2400.             imul di,10              ;Multiply divisor by 10
  2401.             jnc p1_floop            ;Loop while < 5 digits
  2402.  
  2403.             shr dx,1                ;5 digits, divide by 2
  2404.             rcr ax,1                ;and set DI to 50000
  2405.             mov di,50000            ;instead of 100000
  2406.  
  2407. p1_ffinish: xchg dx,ax              ;Multiply by 65536
  2408.             xor ax,ax
  2409.             div di                  ;Divide by 10^digits
  2410.             xchg dx,ax              ;Fractional part in DX
  2411.             pop ax                  ;Restore integer part
  2412.  
  2413. p1_finish:  xchg dx,ax              ;DX:AX = number
  2414.  
  2415.             dec bp                  ;Positive, don't negate
  2416.             jl p1_done
  2417.  
  2418.             neg dx                  ;Negate the result
  2419.             neg ax
  2420.             sbb dx,0
  2421.  
  2422. p1_done:    pop bp di si cx bx      ;Restore registers
  2423.             pop bp                  ;Delete stack frame
  2424.             ret 2                   ;Return
  2425.  
  2426. EndP        atofix
  2427.  
  2428. End
  2429.  
  2430. ~~~C_BITS
  2431. Ideal
  2432.  
  2433. Public      bitcnt,highbit
  2434.  
  2435. Model Tiny
  2436. P186
  2437. CodeSeg
  2438.  
  2439. ;****************** bitcnt() -- Count set bits in integer
  2440. ;int bitcnt(int x);
  2441.  
  2442. x           equ bp+4
  2443.  
  2444. Proc        bitcnt
  2445.  
  2446.             push bp                 ;Set up stack frame
  2447.             mov bp,sp
  2448.             push bx cx              ;Save registers
  2449.  
  2450.             xor cx,cx               ;CX = 0
  2451.             mov ax,[x]              ;AX = number
  2452.             test ax,ax              ;Zero?
  2453.             jz p1_done
  2454.  
  2455. p1_loop:    mov bx,ax               ;Kill last bit
  2456.             dec bx
  2457.             and ax,bx
  2458.             loopnz p1_loop          ;Loop while not zero
  2459.  
  2460. p1_done:    sub ax,cx               ;Negative of CX
  2461.  
  2462.             pop cx bx               ;Restore registers
  2463.             pop bp                  ;Delete stack frame
  2464.             ret 2                   ;Return
  2465.  
  2466. EndP        bitcnt
  2467.  
  2468. ;****************** highbit() -- Find high bit in integer
  2469. ;int highbit(int x);             returns -1 if it was zero
  2470.  
  2471. x           equ bp+4
  2472.  
  2473. Proc        highbit
  2474.  
  2475.             push bp                 ;Set up stack frame
  2476.             mov bp,sp
  2477.             push bx                 ;Save registers
  2478.  
  2479.             mov ax,15               ;Start with bit 15
  2480.             mov bx,[x]              ;BX = number
  2481.  
  2482. p2_loop:    add bx,bx               ;Shift out bit
  2483.             jc p2_done              ;Found a bit?
  2484.             dec ax                  ;Loop back
  2485.             jns p2_loop
  2486.  
  2487. p2_done:    pop bx                  ;Restore registers
  2488.             pop bp                  ;Delete stack frame
  2489.             ret 2                   ;Return
  2490.  
  2491. EndP        highbit
  2492.  
  2493. End
  2494.  
  2495. ~~~C_SQRT
  2496. Ideal
  2497.  
  2498. Public      sqrt
  2499.  
  2500. Model Tiny
  2501. P186
  2502. CodeSeg
  2503.  
  2504. ;****************** sqrt() -- Returns the square root of a
  2505. ;                             long.  Result is an integer.
  2506. ;int sqrt(long num);          60-350 clocks (486)
  2507.  
  2508.  
  2509. num         equ bp+4
  2510.  
  2511. Proc        sqrt
  2512.  
  2513.             push bp                 ;Set up stack frame
  2514.             mov bp,sp
  2515.             push cx dx              ;Save registers
  2516.  
  2517.             mov ax,[num]            ;DX:AX = num
  2518.             mov dx,[num+2]
  2519.  
  2520.             mov cx,32               ;32 bits
  2521.  
  2522. p1_bloop:   add ax,ax               ;Find the highest set bit
  2523.             adc dx,dx
  2524.             jc p1_gotbit
  2525.             loop p1_bloop
  2526.  
  2527. p1_gotbit:  mov ax,1                ;CX = first guess 2^(log2(n)/2)
  2528.             shr cx,1
  2529.             shl ax,cl
  2530.             xchg cx,ax
  2531.  
  2532. p1_loop:    mov ax,[num]            ;DX:AX = num
  2533.             mov dx,[num+2]
  2534.             div cx                  ;AX = num/guess
  2535.             add cx,ax               ;CX = (guess+(num/guess))/2
  2536.             shr cx,1
  2537.             sub ax,cx               ;If the difference is 1
  2538.             cmp ax,1                ;or less, then done
  2539.             ja p1_loop              ;Loop back
  2540.  
  2541.             xchg ax,cx              ;AX = result
  2542.             pop dx cx               ;Restore registers
  2543.             pop bp                  ;Delete stack frame
  2544.             ret 4                   ;Return
  2545.  
  2546. EndP        sqrt
  2547.  
  2548. End
  2549.  
  2550. ~~~C_ROMAN
  2551. Ideal
  2552.  
  2553. Public      roman
  2554.  
  2555. Model Tiny
  2556. CodeSeg
  2557. P386
  2558.  
  2559. ;****************** roman() -- Convert integer to Roman Numerals
  2560.  
  2561. num         equ bp+6
  2562. buf         equ bp+4
  2563.  
  2564. Proc        roman
  2565.  
  2566.             push bp                 ;Set up stack frame
  2567.             mov bp,sp
  2568.             pusha                   ;Save all registers
  2569.  
  2570.             mov di,[buf]            ;DI = buffer
  2571.             mov dx,[num]            ;DX = number
  2572.             mov si,offset RNTbl_1   ;SI, BX = tables
  2573.             mov bx,offset RNTbl_2
  2574.  
  2575. p1_loop:    lodsw                   ;Load size
  2576.             test ax,ax              ;Done?
  2577.             jz p1_done
  2578.  
  2579. p1_iloop:   cmp dx,ax
  2580.             jl p1_lb
  2581.             mov cx,[bx]             ;AX = code
  2582.             mov [di],cl             ;Store first char
  2583.             inc di
  2584.  
  2585.             cmp ch,'.'              ;If second char, then
  2586.             je p1_ilb               ; store second char
  2587.             mov [di],ch
  2588.             inc di
  2589.  
  2590. p1_ilb:     sub dx,ax               ;Reduce number
  2591.             jmp p1_iloop            ;Loop back
  2592.  
  2593. p1_lb:      inc bx                  ;Advance pointer
  2594.             inc bx
  2595.             jmp p1_loop             ;Loop back
  2596.  
  2597. p1_done:    mov [di],al             ;Terminate string
  2598.  
  2599.             popa                    ;Restore registers
  2600.             pop bp                  ;Delete stack frame
  2601.             ret 4                   ;Return
  2602.  
  2603. EndP        roman
  2604.  
  2605. RNTbl_1     dw 1000,900,500,400,100
  2606.             dw 90,50,40,10,9,5,4,1,0
  2607.  
  2608. RNTbl_2     db 'M.CMD.CDC.XCL.XLX.IXV.IVI.'
  2609.  
  2610. End
  2611.  
  2612. ~~~C_CRC16
  2613. Ideal
  2614.  
  2615. Public      crc16
  2616.  
  2617. Model Tiny
  2618. CodeSeg
  2619. P186
  2620.  
  2621. ;****************** crc16() -- Calculate 16-bit CRC
  2622. ;int crc16(void *ptr, int cnt)
  2623.  
  2624. ptr         equ bp+6
  2625. cnt         equ bp+4
  2626.  
  2627. Proc        crc16
  2628.  
  2629.             push bp                 ;Set up stack frame
  2630.             mov bp,sp
  2631.             push bx cx dx si        ;Save registers
  2632.  
  2633.             mov si,[ptr]            ;SI = pointer
  2634.             mov bx,[cnt]            ;BX = count
  2635.  
  2636.             xor dx,dx               ;Start with 0
  2637.  
  2638. p1_loop:    lodsb                   ;Load byte
  2639.             xor dh,al               ;XOR into result
  2640.             mov cx,8                ;8 bits
  2641.  
  2642. p1_iloop:   add dx,dx               ;Shift left
  2643.             jnc $+5                 ;If bit = 1, then
  2644.             xor dx,1021h            ;XOR in CRC value
  2645.             loop p1_iloop           ;Loop back
  2646.  
  2647.             dec bx                  ;Byte loop
  2648.             jnz p1_loop
  2649.  
  2650.             xchg dx,ax              ;Result in AX
  2651.  
  2652. p1_done:    pop si dx cx bx         ;Restore registers
  2653.             pop bp                  ;Delete stack frame
  2654.             ret 4                   ;Return
  2655.  
  2656. EndP        crc16
  2657.  
  2658. End
  2659.  
  2660. ~~~C_CRC32
  2661. Ideal
  2662.  
  2663. Public      crc32
  2664.  
  2665. Model Tiny
  2666. CodeSeg
  2667. P186
  2668.  
  2669. ;****************** crc32() -- Calculate 32-bit CRC
  2670. ;long crc32(void *ptr, int cnt)
  2671.  
  2672. ptr         equ bp+6
  2673. cnt         equ bp+4
  2674.  
  2675. Proc        crc32
  2676.  
  2677.             push bp                 ;Set up stack frame
  2678.             mov bp,sp
  2679.             push bx cx si di        ;Save registers
  2680.  
  2681.             mov si,[ptr]            ;SI = pointer
  2682.             mov bx,[cnt]            ;BX = count
  2683.  
  2684.             xor dx,dx               ;Start with 0
  2685.             xor di,di
  2686.  
  2687. p1_loop:    lodsb                   ;Load byte
  2688.             xor dh,al               ;XOR into result
  2689.             mov cx,8                ;8 bits
  2690.  
  2691. p1_iloop:   add di,di               ;Shift left
  2692.             adc dx,dx
  2693.             jnc $+8                 ;If bit = 1, then
  2694.             xor dx,04C1h            ;XOR in CRC value
  2695.             xor di,1DB7h
  2696.             loop p1_iloop           ;Loop back
  2697.  
  2698.             dec bx                  ;Byte loop
  2699.             jnz p1_loop
  2700.  
  2701.             xchg di,ax              ;Result in DX:AX
  2702.  
  2703. p1_done:    pop di si cx bx         ;Restore registers
  2704.             pop bp                  ;Delete stack frame
  2705.             ret 4                   ;Return
  2706.  
  2707. EndP        crc32
  2708.  
  2709. End
  2710.